﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using SpriteMaker;
using System.Windows.Forms;
using System.ComponentModel;
using System.Globalization;
using System.Drawing.Drawing2D;
using System.Drawing.Design;
using SpriteMaker;
namespace UIMaker
{
    public enum XAlignment
    {
        Center,
        Left,
        Right,
        Top,
        Bottom,
        LeftTop,
        LeftBottom,
        RightTop,
        RightBottom,
        LeftCenter,
        RightCenter,
        TopCenter,
        BottomCenter
    }
    public class SelectedFrame
    {
        public Sprite sprite;
        public Frame frame;
    }
    [TypeConverterAttribute(typeof(PaddingFConverter)),
    DescriptionAttribute("Expand to see...")]
    public class PaddingF
    {
        private float left, right, top, bottom;
        public float Left
        {
            get { return left; }
            set { left = value; }
        }
        public float Right
        {
            get { return right; }
            set { right = value; }
        }
        public float Top
        {
            get { return top; }
            set { top = value; }
        }
        public float Bottom
        {
            get { return bottom; }
            set { bottom = value; }
        }
    }
    public class PaddingFConverter : ExpandableObjectConverter
    {
        public override bool CanConvertTo(ITypeDescriptorContext context,
                                  System.Type destinationType)
        {
            if (destinationType == typeof(PaddingF))
                return true;

            return base.CanConvertTo(context, destinationType);
        }
        public override object ConvertTo(ITypeDescriptorContext context,
                               CultureInfo culture,
                               object value,
                               System.Type destinationType)
        {
            if (destinationType == typeof(System.String) &&
                 value is PaddingF)
            {

                PaddingF so = (PaddingF)value;

                return "Left:" + so.Left +
                       ", Right: " + so.Right +
                       ", Top: " + so.Top +
                       ", Bottom: " + so.Bottom;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
    public enum XControlType
    {
        Unknown,
        Button,
    }
    public class XControl
    {
        protected SizeF sizeRelative;
        protected SizeF sizeAbsolute;
        protected PaddingF margin = new PaddingF();
        protected XAlignment alignment;
        protected Color backgroundColor;
        protected int backgroundFrameID;
        protected XControl parent;
        private bool updateRelativeFromAbsolute;
        public virtual void Update() { }
        public virtual void Render(Graphics g, float parentX, float parentY, float parentW, float parentH) 
        {
            PointF pos = CalculatePosition();
            RectangleF rect = new RectangleF(parentX + pos.X * parentW, parentY + pos.Y * parentH, parentW * sizeRelative.Width, parentH * sizeRelative.Height);
            g.FillRectangle(Brushes.Aqua, rect);
        }
        public PointF CalculatePosition()
        {
            PointF pos = new PointF(margin.Left, margin.Top);
            if (alignment == XAlignment.Bottom)
            {
                pos.Y = 1.0f - margin.Bottom - sizeRelative.Height;
            }
            else if (alignment == XAlignment.BottomCenter)
            {
                pos.Y = 1.0f - margin.Bottom - sizeRelative.Height;
                pos.X = (1.0f - sizeRelative.Width) / 2.0f;
            }
            else if (alignment == XAlignment.Center)
            {
                pos.Y = (1.0f - sizeRelative.Height) / 2.0f;
                pos.X = (1.0f - sizeRelative.Width) / 2.0f;
            }
            else if (alignment == XAlignment.Left)
            {

            }
            else if (alignment == XAlignment.LeftBottom)
            {
                pos.Y = 1.0f - margin.Bottom - sizeRelative.Height;
            }
            else if (alignment == XAlignment.LeftCenter)
            {
                pos.Y = (1.0f - sizeRelative.Height) / 2.0f;
            }
            else if (alignment == XAlignment.LeftTop)
            {
            }
            else if (alignment == XAlignment.Right)
            {
                pos.X = 1.0f + margin.Right - sizeRelative.Width;
            }
            else if (alignment == XAlignment.RightBottom)
            {
                pos.X = 1.0f + margin.Right - sizeRelative.Width;
                pos.Y = 1.0f - margin.Bottom - sizeRelative.Height;
            }
            else if (alignment == XAlignment.RightCenter)
            {
                pos.X = 1.0f + margin.Right - sizeRelative.Width;
                pos.Y = (1.0f - sizeRelative.Height) / 2.0f;
            }
            else if (alignment == XAlignment.RightTop)
            {
                pos.X = 1.0f + margin.Right - sizeRelative.Width;
            }
            else if (alignment == XAlignment.Top)
            {
            }
            else if (alignment == XAlignment.TopCenter)
            {
                pos.X = (1.0f - sizeRelative.Width) / 2.0f;
            }
            return pos;
        }
        public virtual void OnTouchPressed() { }
        public virtual void OnTouchMoved() { }
        public virtual void OnTouchReleased() { }
        public virtual bool IsContainer() { return false; }
        public SizeF GetParentSizeNormalize()
        {
            if (parent != null)
            {
                return Util.SizeNormalize(parent.SizeRelative);
            }
            else
            {
                return Util.SizeNormalize(SizeRelative);
            }
        }
        public virtual SizeF SizeRelative
        {
            get { return sizeRelative; }
            set 
            {
                if (value.Width <= 0 || value.Height <= 0) return;
                sizeRelative = value;
                if (parent != null)
                {
                    sizeAbsolute = new SizeF(parent.SizeAbsolute.Width * sizeRelative.Width, parent.SizeAbsolute.Height * sizeRelative.Height);
                }
            }
        }
        public SizeF SizeAbsolute
        {
            get { return sizeAbsolute; }
            set
            {
                if (value.Width <= 0 || value.Height <= 0) return;
                sizeAbsolute = value;
                if (parent != null)
                {
                    sizeRelative = new SizeF(sizeAbsolute.Width / parent.SizeAbsolute.Width, sizeAbsolute.Height / parent.SizeAbsolute.Height);
                }
                else
                {
                    sizeRelative = Util.SizeNormalize(sizeAbsolute);
                }
            }
        }
        public PaddingF Margin
        {
            get { return margin; }
            set { margin = value; }
        }
        public XAlignment Alignment
        {
            get { return alignment; }
            set { alignment = value; }
        }
        public Color BackgroundColor
        {
            get { return backgroundColor; }
            set { backgroundColor = value; }
        }
        public XControl Parent
        {
            get { return parent; }
            set 
            { 
                parent = value;
                if (parent != null)
                {
                    sizeAbsolute = new SizeF(parent.SizeAbsolute.Width * sizeRelative.Width, parent.SizeAbsolute.Height * sizeRelative.Height);
                }
            }
        }
    }
    public class XContainer : XControl
    {
        public List<XControl> childs = new List<XControl>();
        public override bool IsContainer() { return true; }
        public void AddChild(XControl xcontrol)
        {
            xcontrol.Parent = this;
            childs.Add(xcontrol);
        }
    }
    public class XButton : XControl
    {
        private int animMoveInID;
        private int animMoveOutID;
        private int animPressedID;
        private int animReleasedID;
        private int framePressedID;
        private SelectedFrame frameReleasedID;
        private string spriteName;
        public int AnimMoveInID
        {
            get { return animMoveInID; }
            set { animMoveInID = value; }
        }
        public XButton()
        {
            SizeRelative = new SizeF(0.25f,0.1f);
        }
        [Editor(typeof(SelectSprite), typeof(UITypeEditor))]
        public string Filename
        {
            get { return spriteName; }
            set { spriteName = value; }
        }
        [Editor(typeof(SelectFrame), typeof(UITypeEditor))]
        public SelectedFrame FrameReleased
        {
            get { return frameReleasedID; }
            set { frameReleasedID = value; }
        } 
    }
    public class XScreen : XContainer
    {
        private String name;
        public String Name
        {
            get { return name; }
            set { name = value; }
        }
        [ReadOnlyAttribute(true)]
        public override SizeF SizeRelative
        {
            get { return sizeRelative; }
            set
            {
                if (value.Width <= 0 || value.Height <= 0) return;
                sizeRelative = value;
            }
        }
        public override void Render(Graphics g, float parentX, float parentY, float parentW, float parentH)
        {
            float x = (parentW - SizeAbsolute.Width) / 2;
            float y = (parentH - SizeAbsolute.Height) / 2;
            g.FillRectangle(Brushes.White, x, y, SizeAbsolute.Width, SizeAbsolute.Height);
            foreach (XControl xcontrol in childs)
            {
                xcontrol.Render(g, x, y, SizeAbsolute.Width, SizeAbsolute.Height);
            }
        }
    }
    public class XMenu
    {
        private List<XScreen> screenList = new List<XScreen>();
        public XScreen AddScreen(String name)
        {
            XScreen screen = new XScreen();
            screen.Name = name;
            screenList.Add(screen);
            return screen;
        }
        public XScreen GetScreenByName(String name)
        {
            foreach (XScreen xScreen in screenList)
            {
                if (xScreen.Name == name)
                {
                    return xScreen;
                }
            }
            return null;
        }
    }
    public class XDialog : XContainer
    {
        public XDialog()
        {
            SizeRelative = new SizeF(0.7f,0.7f);
        }
        public override void Render(Graphics g, float parentX, float parentY, float parentW, float parentH)
        {
            PointF pos = CalculatePosition();
            g.DrawRectangle(Pens.Black, parentX + pos.X * parentW, parentY + pos.Y * parentH, SizeRelative.Width * parentW, SizeRelative.Height * parentH);
            foreach (XControl xcontrol in childs)
            {
                xcontrol.Render(g, parentX + pos.X * parentW, parentY + pos.Y * parentH, SizeRelative.Width * parentW, SizeRelative.Height * parentH);
            }
        }
    }
}
